#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <linux/netfilter/xt_state.h>
#include <linux/netfilter/nf_conntrack_common.h>
#include <libiptc/libiptc.h>

#define __DEBUG	printf
#define IPT_ALIGN	XT_ALIGN
#define IPT_STATE_BIT	XT_STATE_BIT

#define IPTABLES_FILTER	"filter"
#define IPT_MATCH_STATE	"state"
#define IPTABLES_FILTER_FORWARD	"FORWARD"
#define IPTC_SUCCESS	1

#define SIZE	128

#define COUNTER_MAP_SET	3

enum {
	CMD_PE_ERR_INTERNAL = 0,
	
};

static int 
iptc_set_policystae( const xt_chainlabel chain, unsigned int rulenum,
		int *state, struct xtc_handle **handle )
{
	struct ipt_entry *e;
	struct chain_head *c;
	unsigned int chainindex, end;

//	iptc_fn = TC_SET_POLICYSTATE;
	//CHECK(*handle);

	if (!(c = iptcc_find_label(chain, *handle))) {
		errno = ENOENT;
		return 0;
	}
#if 0
	chainindex = iptcb_entry2index(*handle, c->start);
	end = entry2index(*handle, c->end);

	if (chainindex + rulenum > end) {
		errno = E2BIG;
		return 0;
	}
#endif
//	iptcb_offset2entry(struct xtc_handle *h, unsigned int offset)
	e = iptcb_offset2entry(*handle, 0 + rulenum);

	(*handle)->chain_iterator_cur->counter_map[chainindex + rulenum].maptype
		= COUNTER_MAP_SET;

	memcpy(&e->disabled, state, sizeof(int));

	set_changed(*handle);

	return 1;

}

int main( int argc, char **argv )
{
	int ret = -1;
	char chain[32];
	int index = 0;
	int state = -1;
	struct xtc_handle *handle;
	
	if ( argc < 4 ) {
		printf( "Invalid paramers too small!\n" );
		return -1;
	}

	strncpy( chain, argv[1], SIZE );
	index = atoi( argv[2] );
	state = atoi( argv[3] );
	
	handle=iptc_init(IPTABLES_FILTER);
	if(handle == NULL){
		ret=CMD_PE_ERR_INTERNAL;
		__DEBUG(" Can't initialize iptc handle!\n");
		goto out;
	}

	/* control switch for the ipt_entry */
	if ( iptc_set_policystae( chain,index-1,&state,&handle ) != IPTC_SUCCESS ) {
		ret = CMD_PE_ERR_INTERNAL;
		__DEBUG( "Can't change rule status!\n" );
		goto out;
	}

	if(iptc_commit(handle) != IPTC_SUCCESS)
	{
		ret=CMD_PE_ERR_INTERNAL;
		__DEBUG(" Can't commit changes!" );
		goto out;
	}

out:
	return ret;
}
